package com.qmock.pay.security;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.IOException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
 * Created with IntelliJ IDEA.
 * User: tianqing.wang
 * Date: 13-8-8
 * Time: 上午10:11
 * To change this template use File | Settings | File Templates.
 */
public class RSA {
    //非对称加密秘钥算法
    public static final String KEY_ALGORITHM="RSA";
    //公钥
    public static final String PUBLIC_KEY="RSAPublicKey";
    //秘钥
    public static final String PRIVATE_KEY="RSAPrivateKey";
    /**
     * BASE64Decoder
     */
    private static BASE64Decoder decoder;
    /**
     * BASE64Encoder
     */
    private static BASE64Encoder encoder;
/**
 * RSA密钥长度默认的为1024位，
 * 密钥的长度必须是64的倍数
 * 范围在512~65536位之间
 * */


    /**
     * 私钥解密
     * @param data 待解密的数据
     * @param key 私钥
     * @return 解密数据
     * @throws Exception
     * */
    public static byte[] decryptByPrivateKey(byte[] data,byte[] key)throws Exception{
//取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
        PrivateKey pk = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE,pk);
        return cipher.doFinal(data);
    }

    /**公钥解密
     * @param data 待解密数据
     * @param key 公钥
     * @return byte[] 解密数据
     * @throws Exception
     * */
    public static byte[] decryptByPublicKey(byte[] data,byte[] key) throws Exception{
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey pk = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE,pk);
        return cipher.doFinal(data);
    }

    /**公钥加密
     * @param data 代加密数据
     * @param key 公钥
     * @return byte[] 加密数据
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,publicKey1);
        return cipher.doFinal(data);
    }


    /**
     * 私钥加密
     * @param data 待解密的数据
     * @param key 私钥
     * @return 解密数据
     * @throws Exception
     * */
    public static byte[] encryptByPrivateKey(byte[] data,byte[] key)throws Exception{
//取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
        PrivateKey pk = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,pk);
        return cipher.doFinal(data);
    }

    /**取得私钥
     * @param keyMap 秘钥map
     * @return byte[] 私钥
     * @throws Exception
     * */
    public static byte[] getPrivteKey(Map<String,Object>keyMap) throws Exception{
        Key key =(Key) keyMap.get(PRIVATE_KEY);
        return key.getEncoded();
    }
    /**
     * 取得公钥
     * @param keyMap 秘钥Map
     * @return byte[] 公钥
     * @throws Exception
     * */
    public static byte[] getPublicKey(Map<String,Object>keyMap) throws Exception{
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return key.getEncoded();
    }

    /**
     * 初始化密钥
     * @return Map 密钥Map
     * @throws Exception
     * */
    public static Map<String,Object> initKey(int keySize) throws Exception{
/**实例化密钥对*/
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
//初始化密钥生成器
        keyPairGenerator.initialize(keySize);
//生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
//公钥
        RSAPublicKey initPublicKey = (RSAPublicKey)keyPair.getPublic();
//密钥
        RSAPrivateKey initPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
//把密钥打包
        Map<String, Object> keyMap = new HashMap<String, Object>();
        keyMap.put(PRIVATE_KEY,initPrivateKey);
        keyMap.put(PUBLIC_KEY,initPublicKey);
        return keyMap;
    }

    public static String encode(byte[] b){
        return getBASE64Encoder().encodeBuffer(b);
    }

    public static byte[] decode(String s) throws IOException {
        return getBASE64Decoder().decodeBuffer(s);
    }

    private static BASE64Encoder getBASE64Encoder() {
        if(encoder == null){
            encoder = new BASE64Encoder();
        }
        return encoder;
    }

    private static BASE64Decoder getBASE64Decoder(){
        if(decoder == null){
            decoder = new BASE64Decoder();
        }
        return decoder;
    }
}
